"use client";

import { useState, useEffect } from "react";
import { Button } from "./ui/button";
import { Input } from "./ui/input";
import { Label } from "./ui/label";
import {
	Select,
	SelectContent,
	SelectItem,
	SelectTrigger,
	SelectValue,
} from "./ui/select";
import { Settings, Terminal, Loader2, HelpCircle, Eye, EyeOff } from "lucide-react";
import { useSettings } from "@/lib/hooks/use-settings";
import { Textarea } from "./ui/textarea";
import { Slider } from "./ui/slider";
import {
	Tooltip,
	TooltipContent,
	TooltipProvider,
	TooltipTrigger,
} from "./ui/tooltip";
import { toast } from "@/lib/use-toast";
import { cn } from "@/lib/utils";

export const Icons = {
	openai: (props: any) => (
		<svg
			fill="currentColor"
			viewBox="0 0 24 24"
			role="img"
			xmlns="http://www.w3.org/2000/svg"
			{...props}
		>
			<path d="M22.2819 9.8211a5.9847 5.9847 0 0 0-.5157-4.9108 6.0462 6.0462 0 0 0-6.5098-2.9A6.0651 6.0651 0 0 0 4.9807 4.1818a5.9847 5.9847 0 0 0-3.9977 2.9 6.0462 6.0462 0 0 0 .7427 7.0966 5.98 5.98 0 0 0 .511 4.9107 6.051 6.051 0 0 0 6.5146 2.9001A5.9847 5.9847 0 0 0 13.2599 24a6.0557 6.0557 0 0 0 5.7718-4.2058 5.9894 5.9894 0 0 0 3.9977-2.9001 6.0557 6.0557 0 0 0-.7475-7.0729zm-9.022 12.6081a4.4755 4.4755 0 0 1-2.8764-1.0408l.1419-.0804 4.7783-2.7582a.7948.7948 0 0 0 .3927-.6813v-6.7369l2.0264 1.1706a.071.071 0 0 1 .038.052v5.5826a4.504 4.504 0 0 1-4.4929 4.4944zm-9.6607-4.1254a4.4708 4.4708 0 0 1-.5346-3.0137l.142.0852 4.783 2.7582a.7712.7712 0 0 0 .7806 0l5.8428-3.3685v2.3324a.0804.0804 0 0 1-.0332.0615L9.74 19.9502a4.4992 4.4992 0 0 1-6.1408-1.6464zM2.3408 7.8956a4.485 4.485 0 0 1 2.3655-1.9728V11.6a.7664.7664 0 0 0 .3879.6765l5.8144 3.3543-2.0264 1.1706a.0757.0757 0 0 1-.071 0l-4.8303-2.7865A4.504 4.504 0 0 1 2.3408 7.8956zm16.0788 3.7951-5.8144-3.3543 2.0264-1.1706a.0757.0757 0 0 1 .071 0l4.8303 2.7913a4.4944 4.4944 0 0 1-.6765 8.1042v-5.6772a.79.79 0 0 0-.4068-.6813zm2.0834-3.0089-.142-.0852-4.7782-2.7913a.7759.7759 0 0 0-.7854 0L9.409 9.2297V6.8974a.0662.0662 0 0 1 .0284-.0615l4.8303-2.7866a4.4992 4.4992 0 0 1 6.6802 4.66zM8.3065 12.863l-2.02-1.1658a.0804.0804 0 0 1-.038-.0567V6.0742a4.4992 4.4992 0 0 1 7.3757-3.4537l-.142.0805L8.704 5.459a.7948.7948 0 0 0-.3927.6813zm1.0976-2.3654 2.602-1.4998 2.6069 1.4998v2.9994l-2.5974 1.4997-2.6067-1.4997Z" />
		</svg>
	),
	settings: Settings,
	terminal: Terminal,
	spinner: Loader2,
};

interface AIProviderConfigProps {
	onSubmit: (data: AIProviderData) => void;
	defaultPreset?: {
		provider: "openai" | "native-ollama" | "custom" | "screenpipe-cloud";
		apiKey?: string;
		baseUrl?: string;
		modelName?: string;
		maxContextChars?: number;
		prompt?: string;
		id?: string;
	};
}

interface AIProviderData {
	provider: "openai" | "native-ollama" | "custom" | "screenpipe-cloud";
	apiKey?: string;
	baseUrl?: string;
	modelName?: string;
	maxContextChars?: number;
	prompt?: string;
	id?: string;
}

interface OpenAIModel {
	id: string;
	created?: number;
	owned_by?: string;
}

export const DEFAULT_PROMPT = `Rules:
- You can analyze/view/show/access videos to the user by putting .mp4 files in a code block (we'll render it) like this: \`/users/video.mp4\`, use the exact, absolute, file path from file_path property
- Do not try to embed video in links (e.g. [](.mp4) or https://.mp4) instead put the file_path in a code block using backticks
- Do not put video in multiline code block it will not render the video (e.g. \`\`\`bash\n.mp4\`\`\` IS WRONG) instead using inline code block with single backtick
- Always answer my question/intent, do not make up things
`;


export function AIProviderConfig({
	onSubmit,
	defaultPreset,
}: AIProviderConfigProps) {
	const [selectedProvider, setSelectedProvider] = useState<
		AIProviderData["provider"]
	>(defaultPreset?.provider || "openai");
	const { settings } = useSettings();
	const [isLoading, setIsLoading] = useState(false);
	const [openaiModels, setOpenAIModels] = useState<OpenAIModel[]>([]);
	const [isLoadingModels, setIsLoadingModels] = useState(false);
	const [idError, setIdError] = useState<string | null>(null);
	const [showApiKey, setShowApiKey] = useState(false);
	const [formData, setFormData] = useState<AIProviderData>({
		provider: defaultPreset?.provider || "openai",
		apiKey: defaultPreset?.apiKey || "",
		baseUrl: defaultPreset?.baseUrl || "",
		modelName: defaultPreset?.modelName || "",
		maxContextChars: defaultPreset?.maxContextChars || 512000,
		prompt: defaultPreset?.prompt || DEFAULT_PROMPT,
		id: defaultPreset?.id || "",
	});

	const validateId = (id: string | undefined): boolean => {
		if (!id?.trim()) {
			setIdError("name is required");
			return false;
		}

		// Check if ID ends with 'copy' (case insensitive)
		if (id.trim().toLowerCase().endsWith("copy")) {
			setIdError("name cannot end with 'copy'");
			return false;
		}

		// Check for duplicate IDs, excluding the current preset being edited
		const isDuplicate = settings?.aiPresets?.some(
			(preset) => preset.id.toLowerCase() === id.toLowerCase() && preset.id !== defaultPreset?.id
		);

		if (isDuplicate) {
			setIdError("name already exists");
			return false;
		}

		setIdError(null);
		return true;
	};

	const handleIdChange = (value: string) => {
		setFormData((prev) => ({ ...prev, id: value }));
		validateId(value);
	};

	const fetchOpenAIModels = async (baseUrl: string, apiKey: string) => {
		setIsLoadingModels(true);
		try {
			const response = await fetch(`${baseUrl}/models`, {
				headers: {
					Authorization: `Bearer ${apiKey}`,
					"Content-Type": "application/json",
				},
			});

			if (!response.ok) {
				throw new Error("failed to fetch models");
			}

			const data = await response.json();
			setOpenAIModels(data.data || []);
		} catch (error) {
			console.error("error fetching models:", error);
			setOpenAIModels([]);
		} finally {
			setIsLoadingModels(false);
		}
	};

	const fetchOllamaModels = async (baseUrl: string) => {
		setIsLoadingModels(true);
		try {
			const response = await fetch(`${baseUrl}/models`);

			if (!response.ok) {
				throw new Error("failed to fetch ollama models");
			}

			const data = (await response.json()) as {
				data: OpenAIModel[];
			};
			setOpenAIModels(data.data || []);
		} catch (error) {
			console.error("error fetching ollama models:", error);
			setOpenAIModels([]);
		} finally {
			setIsLoadingModels(false);
		}
	};

	useEffect(() => {
		setOpenAIModels([]);
		if (selectedProvider === "openai" && formData.apiKey) {
			setOpenAIModels([
				{ id: "gpt-4", },
				{
					id: "gpt-3.5-turbo",
				},
			]);
		} else if (selectedProvider === "native-ollama") {
			const baseUrl = "http://localhost:11434/v1";
			fetchOllamaModels(baseUrl);
		} else if (selectedProvider === "screenpipe-cloud") {
			fetchOpenAIModels(
				"https://ai-proxy.i-f9f.workers.dev/v1",
				settings?.user?.token ?? "",
			);
		} else if (
			selectedProvider === "custom" &&
			formData.baseUrl &&
			formData.apiKey
		) {
			fetchOpenAIModels(formData.baseUrl, formData.apiKey);
		}
	}, [selectedProvider, formData.apiKey, formData.baseUrl]);

	const handleSubmit = async (e: React.FormEvent) => {
		e.preventDefault();

		if (!validateId(formData.id)) {
			return;
		}

		setIsLoading(true);
		try {
			onSubmit({
				...formData,
				id: formData.id?.trim() || "",
			});
		} finally {
			setIsLoading(false);
		}
	};

	return (
		<div className="w-full space-y-6 rounded-lg bg-card p-6">
			<div>
				<h2 className="text-lg font-semibold">
					{defaultPreset?.id ? "edit ai provider" : "ai provider"}
				</h2>
				<p className="text-sm text-muted-foreground">
					{defaultPreset?.id
						? "modify your ai provider settings"
						: "configure your ai provider settings"}
				</p>
			</div>

			<form onSubmit={handleSubmit} className="space-y-4">
				<div className="space-y-2">
					<Label htmlFor="name" className="flex items-center gap-2">
						name
						{idError && (
							<span className="text-xs text-destructive font-normal">
								{idError}
							</span>
						)}
					</Label>
					<Input
						id="name"
						type="text"
						placeholder="enter preset name"
						value={formData.id || undefined}
						onChange={(e) => handleIdChange(e.target.value)}
						className={cn(
							"font-mono",
							idError && "border-destructive focus-visible:ring-destructive"
						)}
						autoComplete="off"
						autoCorrect="off"
						autoCapitalize="off"
						disabled={Boolean(defaultPreset?.id) && !defaultPreset?.id?.endsWith("-copy")}
					/>
				</div>

				<div className="grid grid-cols-4 gap-4">
					<Button
						type="button"
						variant={selectedProvider === "openai" ? "default" : "outline"}
						className="flex h-24 flex-col items-center justify-center gap-2"
						onClick={() => {
							setSelectedProvider("openai");
							setFormData({ ...formData, provider: "openai" });
						}}
					>
						<Icons.openai className="h-8 w-8" />
						<span>openai</span>
					</Button>

					<Button
						type="button"
						variant={
							selectedProvider === "native-ollama" ? "default" : "outline"
						}
						className="flex h-24 flex-col items-center justify-center gap-2"
						onClick={() => {
							setSelectedProvider("native-ollama");
							setFormData({
								...formData,
								provider: "native-ollama",
								baseUrl: "http://localhost:11434/v1",
							});
						}}
					>
						<Icons.terminal className="h-8 w-8" />
						<span>ollama</span>
					</Button>

					<Button
						type="button"
						disabled={!settings?.user?.token}
						variant={
							selectedProvider === "screenpipe-cloud" ? "default" : "outline"
						}
						className="flex h-24 flex-col items-center justify-center gap-2"
						onClick={() => {
							setSelectedProvider("screenpipe-cloud");
							setFormData({ ...formData, provider: "screenpipe-cloud",
								baseUrl: "https://ai-proxy.i-f9f.workers.dev/v1",
							 });
						}}
					>
						<Icons.terminal className="h-8 w-8" />
						<span>screenpipe</span>
						{
							!settings?.user?.token && (
								<span className="text-xs text-destructive font-normal">
									login to screenpipe to use this provider
								</span>
							)
						}
					</Button>

					<Button
						type="button"
						variant={selectedProvider === "custom" ? "default" : "outline"}
						className="flex h-24 flex-col items-center justify-center gap-2"
						onClick={() => {
							setSelectedProvider("custom");
							setFormData({
								...formData,
								provider: "custom",
								baseUrl: "http://localhost:11434/v1",
							});
						}}
					>
						<Icons.settings className="h-8 w-8" />
						<span>custom</span>
					</Button>
				</div>

				{selectedProvider === "openai" && (
					<div className="space-y-4">
						<div className="space-y-2">
							<Label htmlFor="apiKey">api key</Label>
							<div className="relative">
								<Input
									id="apiKey"
									type={showApiKey ? "text" : "password"}
									placeholder="sk-..."
									value={formData.apiKey || ""}
									onChange={(e) =>
										setFormData({ ...formData, apiKey: e.target.value })
									}
									className="pr-10"
								/>
								<Button
									type="button"
									variant="ghost"
									size="icon"
									className="absolute right-0 top-0 h-full px-3 py-2 hover:bg-transparent"
									onClick={() => setShowApiKey(!showApiKey)}
								>
									{showApiKey ? (
										<EyeOff className="h-4 w-4" />
									) : (
										<Eye className="h-4 w-4" />
									)}
								</Button>
							</div>
						</div>
						<div className="space-y-2">
							<Label htmlFor="model">model</Label>
							<Select
								value={formData.modelName}
								onValueChange={(value) =>
									setFormData({ ...formData, modelName: value })
								}
							>
								<SelectTrigger>
									<SelectValue
										placeholder={
											isLoadingModels ? "loading models..." : "select model"
										}
									/>
								</SelectTrigger>
								<SelectContent>
									{openaiModels.length > 0 ? (
										openaiModels.map((model) => (
											<SelectItem key={model.id} value={model.id}>
												{model.id}
											</SelectItem>
										))
									) : (
										<SelectItem value="no-models" disabled>
											{isLoadingModels ? "loading..." : "no models found"}
										</SelectItem>
									)}
								</SelectContent>
							</Select>
						</div>
					</div>
				)}

				{selectedProvider === "native-ollama" && (
					<div className="space-y-4">
						<div className="space-y-2">
							<Label htmlFor="baseUrl">base url</Label>
							<Input
								id="baseUrl"
								type="text"
								placeholder="http://localhost:11434"
								value={formData.baseUrl || ""}
								onChange={(e) =>
									setFormData({ ...formData, baseUrl: e.target.value })
								}
							/>
						</div>
						<div className="space-y-2">
							<Label htmlFor="model">model</Label>
							<Select
								value={formData.modelName}
								onValueChange={(value) =>
									setFormData({ ...formData, modelName: value })
								}
							>
								<SelectTrigger>
									<SelectValue
										placeholder={
											isLoadingModels ? "loading models..." : "select model"
										}
									/>
								</SelectTrigger>
								<SelectContent>
									{openaiModels.length > 0 ? (
										openaiModels.map((model) => (
											<SelectItem key={model.id} value={model.id}>
												{model.id}
											</SelectItem>
										))
									) : (
										<SelectItem value="no-models" disabled>
											{isLoadingModels ? "loading..." : "no models found"}
										</SelectItem>
									)}
								</SelectContent>
							</Select>
						</div>
					</div>
				)}

				{selectedProvider === "screenpipe-cloud" && (
					<div className="space-y-4">
						<div className="space-y-2">
							<Label htmlFor="model">model</Label>
							<Select
								value={formData.modelName}
								onValueChange={(value) =>
									setFormData({ ...formData, modelName: value })
								}
							>
								<SelectTrigger>
									<SelectValue
										placeholder={
											isLoadingModels ? "loading models..." : "select model"
										}
									/>
								</SelectTrigger>
								<SelectContent>
									{openaiModels.length > 0 ? (
										openaiModels.map((model) => (
											<SelectItem key={model.id} value={model.id}>
												{model.id}
											</SelectItem>
										))
									) : (
										<SelectItem value="no-models" disabled>
											{isLoadingModels ? "loading..." : "no models found"}
										</SelectItem>
									)}
								</SelectContent>
							</Select>
						</div>
					</div>
				)}

				{selectedProvider === "custom" && (
					<div className="space-y-4">
						<div className="space-y-2">
							<Label htmlFor="baseUrl">base url</Label>
							<Input
								id="baseUrl"
								type="text"
								placeholder="https://api.example.com/v1"
								value={formData.baseUrl || ""}
								onChange={(e) =>
									setFormData({ ...formData, baseUrl: e.target.value })
								}
							/>
						</div>
						<div className="space-y-2">
							<Label htmlFor="apiKey">api key</Label>
							<div className="relative">
								<Input
									id="apiKey"
									type={showApiKey ? "text" : "password"}
									placeholder="your-api-key"
									value={formData.apiKey || ""}
									onChange={(e) =>
										setFormData({ ...formData, apiKey: e.target.value })
									}
									className="pr-10"
								/>
								<Button
									type="button"
									variant="ghost"
									size="icon"
									className="absolute right-0 top-0 h-full px-3 py-2 hover:bg-transparent"
									onClick={() => setShowApiKey(!showApiKey)}
								>
									{showApiKey ? (
										<EyeOff className="h-4 w-4" />
									) : (
										<Eye className="h-4 w-4" />
									)}
								</Button>
							</div>
						</div>
						<div className="space-y-2">
							<Label htmlFor="model">model</Label>
							<Select
								value={formData.modelName}
								onValueChange={(value) =>
									setFormData({ ...formData, modelName: value })
								}
							>
								<SelectTrigger>
									<SelectValue
										placeholder={
											isLoadingModels ? "loading models..." : "select model"
										}
									/>
								</SelectTrigger>
								<SelectContent>
									{openaiModels.length > 0 ? (
										openaiModels.map((model) => (
											<SelectItem key={model.id} value={model.id}>
												{model.id}
											</SelectItem>
										))
									) : (
										<SelectItem value="no-models" disabled>
											{isLoadingModels ? "loading..." : "no models found"}
										</SelectItem>
									)}
								</SelectContent>
							</Select>
						</div>
					</div>
				)}

				<div className="space-y-4">
					<div className="space-y-2">
						<Label htmlFor="maxContextChars" className="flex items-center">
							max context{" "}
							<TooltipProvider>
								<Tooltip>
									<TooltipTrigger asChild>
										<HelpCircle className="ml-2 h-4 w-4 cursor-default" />
									</TooltipTrigger>
									<TooltipContent side="right">
										<p>
											maximum number of characters (think 4 characters per
											token) to send to the ai model. <br />
											usually, openai models support up to 200k tokens, which is
											roughly 1m characters.
										</p>
									</TooltipContent>
								</Tooltip>
							</TooltipProvider>
						</Label>
						<div className="flex items-center gap-4">
							<Slider
								id="maxContextChars"
								min={10000}
								max={1000000}
								step={10000}
								value={[formData.maxContextChars || 512000]}
								onValueChange={([value]) =>
									setFormData({ ...formData, maxContextChars: value })
								}
								className="flex-grow"
							/>
							<span className="min-w-[60px] text-right">
								{((formData.maxContextChars || 512000) / 1000).toFixed(0)}k
							</span>
						</div>
					</div>

					<div className="space-y-2">
						<Label htmlFor="prompt">prompt</Label>
						<Textarea
							id="prompt"
							value={formData.prompt || DEFAULT_PROMPT}
							onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) =>
								setFormData({ ...formData, prompt: e.target.value })
							}
							placeholder="enter your custom prompt here"
							className="min-h-[100px]"
						/>
					</div>
				</div>

				<Button
					type="submit"
					className="w-full"
					disabled={
						isLoading ||
						Boolean(!formData.id?.length && !formData.modelName?.length)
					}
				>
					{isLoading ? (
						<Icons.spinner className="mr-2 h-4 w-4 animate-spin" />
					) : null}
					{defaultPreset ? "save changes" : "continue"}
				</Button>
			</form>
		</div>
	);
}
